-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Require global opt-in for distributed transactions #76376
Require global opt-in for distributed transactions #76376
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @roji Issue DetailsThis adds a static, global TransactionManager.ImplicitDistributedTransactions flag, which must be explicitly turned on in order for distributed transactions to be supported. The reasoning here, as advocated by @ajcvickers, is that back in .NET Framework many users were unintentionally causing escalation to a distributed transaction through improper use of TransactionScope, etc. This flag protects users interested in using TransactionScope but who do not want distributed transactions; this is important as distributed transactions shouldn't be used lightly and without careful consideration (dependency on MSDTC - an external component, considerable perf impact, portability to non-Windows platforms...). Re the flag itself, TransactionManager already has global settings managing transactions. Re the name ImplicitDistributedTransactions, there's a possibility we'd introduce cross-platform distributed transactions into System.Transactions (#71769); if that happens, users will very explicitly create distributed transactions, and would not need to set this flag (hence "Implicit"). /cc @ajcvickers
|
28f3cc5
to
198054d
Compare
Is the intent here to backport this to release/7.0? |
src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs
Outdated
Show resolved
Hide resolved
Yeah, this is something @ajcvickers and I just discussed, despite it being quite late. Not doing this in 7.0 would make it a breaking change later - @ajcvickers will be bringing this to tactics ASAP. |
src/libraries/System.Transactions.Local/src/System/Transactions/TransactionManager.cs
Outdated
Show resolved
Hide resolved
Can we also add this as a trimming feature flag that is off by default to allow trimming the distributed transactions code? |
Tagging subscribers to 'linkable-framework': @eerhardt, @vitek-karas, @LakshanF, @sbomer, @joperezr Issue DetailsThis adds a static, global TransactionManager.ImplicitDistributedTransactions flag, which must be explicitly turned on in order for distributed transactions to be supported. The reasoning here, as advocated by @ajcvickers, is that back in .NET Framework many users were unintentionally causing escalation to a distributed transaction through improper use of TransactionScope, etc. This flag protects users interested in using TransactionScope but who do not want distributed transactions; this is important as distributed transactions shouldn't be used lightly and without careful consideration (dependency on MSDTC - an external component, considerable perf impact, portability to non-Windows platforms...). Re the flag itself, TransactionManager already has global settings managing transactions. Re the name ImplicitDistributedTransactions, there's a possibility we'd introduce cross-platform distributed transactions into System.Transactions (#71769); if that happens, users will very explicitly create distributed transactions, and would not need to set this flag (hence "Implicit"). /cc @ajcvickers
|
@roji this was approved by Tactics. Pleased ping me when the unresolved of the feedback is addressed so I can merge it. |
roji#3 will solve the trimming issues without adding an ILLink feature switch. |
I've tried to do a manual test that the code gets trimmed, and I can't see it happening. I did this by having a minimal console program with a csproj to my locally-build System.Transactions.Local.dll with this PR's changes; running the application after publishing throws Without setting ImplicitDistributedTransactions and publishing trimmed, System.Transaction.Local.dll is 226,304. Inspecting the System.Transactions.Local.dll with DotPeek seems to show all the distributed transaction types - including DtcTransactionConnector - although these should be trimmed. Console program// #pragma warning disable IL2026
// TransactionManager.ImplicitDistributedTransactions = true;
// #pragma warning restore IL2026
Console.WriteLine(typeof(TransactionScope).Assembly.Location);
await using var conn1 = new SqlConnection("Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false");
await using var conn2 = new SqlConnection("Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false");
using (var scope = new TransactionScope())
{
conn1.Open();
conn2.Open();
} csproj: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<PublishTrimmed>true</PublishTrimmed>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="3.0.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="C:\projects\runtime\artifacts\bin\System.Transactions.Local\Debug\net7.0-windows\System.Transactions.Local.dll" />
</ItemGroup>
</Project> |
You should check which type references |
@teo-tsirpanis, when you prototyped it, did you validate everything was getting trimmed away? |
Unfortunately not. 😢 I thought it would be OK since trimming warnings were unsuppressed and did not show up. |
Yeah, I don't see how this construction would enable trimming. EDIT: I see now that the object which is the choke point is only allocated from the static property setter, in which case I see how that would work as long as that property setter is never used. |
I explained how (I thought) it works in roji#3 (comment). Was any of my assumptions wrong? |
I wrote a tiny program that follows the same logic and it works. using ClassLibrary1;
namespace TrimTest
{
internal static class Program
{
static void Main()
{
Console.WriteLine("Hello, World!");
Call(null);
}
static void Call(I? i) => i?.F();
}
} In another library namespace ClassLibrary1
{
public interface I { void F(); }
public class C : I { public void F() { } }
}
@roji if you can send the published trimmed app I will take a look. |
6b5e14f
to
ac77f7c
Compare
@teo-tsirpanis sent you an email offline, thanks! Also squashed and rebased over latest release/7.0. |
Thanks for the email @roji. I inspected the trimmed assemblies and The trim-unsafe code, the P/Invoke that does the COM interop is removed. Removing more code will need additional refactorings. |
@teo-tsirpanis thanks, yeah - I mistakenly looked at ITransactionConnector instead of DtcTransactionConnector, I can indeed see the latter getting trimmed (and thanks for the ILSpy tip, it's indeed very useful also for understanding who's referencing a type, keeping it from getting trimmed). However, as the actual assembly sizes show (2.5k diff), this change alone doesn't allow any significant trimming as there are other references. In order to get real benefits here, it seems that all the trimmable code would have to be refactored behind ITransactionConnector. As we're snapping for 7.0 GA on Monday, I've opened #76791 to track doing this for 8.0. @carlossanlop this is now ready to merge as-is. |
ac77f7c
to
3c44295
Compare
/azp run |
You have several pipelines (over 10) configured to build pull requests in this repository. Specify which pipelines you would like to run by using /azp run [pipelines] command. You can specify multiple pipelines using a comma separated list. |
Thanks for letting me know. I saw you tried to re-run the CI but the command was incomplete. I manually re-ran the single failed leg and will merge once it finishes (assuming none of the failures look related to this change). |
CI re-run passed, all green. Approved and signed-off. Ready to merge. |
Closes dotnet#76469 (cherry picked from commit 2070def)
@carlossanlop the PR adds XML docs to the new API (ImplicitDistributedTransactions), but do I need to update the XMLs manually in https://github.com/dotnet/dotnet-api-docs? |
dotnet-api-docs is the source of truth, so yes, please add it there too. |
OK. Does the XML need to be generated first with the placeholders, or do I just creat something myself? (sorry, I really don't know much about how this all works) |
You can port the triple slash docs automatically to dotnet-api-docs using the You would use a command like this:
|
This adds a static, global TransactionManager.ImplicitDistributedTransactions flag, which must be explicitly turned on in order for distributed transactions to be supported.
The reasoning here, as advocated by @ajcvickers, is that back in .NET Framework many users were unintentionally causing escalation to a distributed transaction through improper use of TransactionScope, etc. This flag protects users interested in using TransactionScope but who do not want distributed transactions; this is important as distributed transactions shouldn't be used lightly and without careful consideration (dependency on MSDTC - an external component, considerable perf impact, portability to non-Windows platforms...).
Re the flag itself, TransactionManager already has global settings managing transactions. Re the name ImplicitDistributedTransactions, there's a possibility we'd introduce cross-platform distributed transactions into System.Transactions (#71769); if that happens, users will very explicitly create distributed transactions, and would not need to set this flag (hence "Implicit").
/cc @ajcvickers
Closes #76469